import forge from 'node-forge';

export interface EncryptedPayload {
    encrypted: string;
    nonce: string;
    data: string;
}

export interface SignedResponse<T = Record<string, any>> {
    data: T;
    timestamp: string;
    signature: string;
}

/**
 * 使用 AES + RSA 混合加密 payload
 */
export function encryptPayload(payload: Record<string, any>, serverPublicKey: string): EncryptedPayload {
    const aesKey = forge.random.getBytesSync(32);
    const iv = forge.random.getBytesSync(16);

    const plaintext = JSON.stringify(payload);

    const cipher = forge.cipher.createCipher('AES-CBC', aesKey);
    cipher.start({iv});
    cipher.update(forge.util.createBuffer(plaintext, 'utf8'));
    cipher.finish();

    const encryptedData = cipher.output.getBytes();

    const publicKey = forge.pki.publicKeyFromPem(serverPublicKey);
    const encryptedKey = publicKey.encrypt(aesKey, 'RSA-OAEP');

    return {
        encrypted: forge.util.encode64(encryptedKey),
        nonce: forge.util.encode64(iv),
        data: forge.util.encode64(encryptedData),
    };
}

/**
 * 验证服务器返回的数据签名
 */
export function verifySignature<T = Record<string, any>>(response: SignedResponse<T>, serverPublicKey: string): boolean {
    if (!response.signature || !response.data || !response.timestamp) return false;

    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - Number(response.timestamp)) > 300) {
        return false;
    }
    // 先合并 data 与 timestamp
    const signData: Record<string, any> = {...response.data, timestamp: response.timestamp};

    // 对 key 排序
    const sortedKeys = Object.keys(signData).sort();
    const sortedData: Record<string, any> = {};
    for (const key of sortedKeys) {
        sortedData[key] = signData[key];
    }

    // JSON 字符串
    const raw = JSON.stringify(sortedData);

    // MD5 -> HEX
    const md5 = forge.md.md5.create();
    md5.update(raw, 'utf8');
    const md5Hex = md5.digest().toHex().toUpperCase();

    // SHA256
    const sha256 = forge.md.sha256.create();
    sha256.update(md5Hex, 'utf8');

    const publicKey = forge.pki.publicKeyFromPem(serverPublicKey);
    const decodedSignature = forge.util.decode64(response.signature);
    try {
        return publicKey.verify(sha256.digest().bytes(), decodedSignature);
    } catch (e) {
        return false;
    }
}
